package org.elucid.gadmin.ui;

import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.JTextPane;
import javax.swing.KeyStroke;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.text.Element;
import javax.swing.text.StyledEditorKit;
import javax.swing.text.View;
import javax.swing.text.ViewFactory;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;
import javax.swing.undo.UndoableEdit;

/**
 * 
 * @see http://www.boplicity.net/confluence/display/Java/Xml+syntax+highlighting+in+Swing+JTextPane
 * 
 * @author george
 * 
 */
public class GTextPane extends JTextPane {

	UndoManager manager;
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -3973560317405564387L;

	public GTextPane() {

		// Set editor kit
		this.setEditorKitForContentType("application/x-sql", new GEditorKit());
		this.setContentType("application/x-sql");

		this.setEditable(true); // Editable
		
		// Create the undo manager and actions
		manager = new UndoManager();
		this.getDocument().addUndoableEditListener(manager);
 
		Action undoAction = new UndoAction(manager);
		Action redoAction = new RedoAction(manager);

		// Assign the actions to keys
		int shortcut = Toolkit.getDefaultToolkit ().getMenuShortcutKeyMask();
		this.registerKeyboardAction(undoAction, KeyStroke.getKeyStroke(KeyEvent.VK_Z, shortcut),
				JComponent.WHEN_FOCUSED);
		this.registerKeyboardAction(redoAction, KeyStroke.getKeyStroke(KeyEvent.VK_Z, shortcut + InputEvent.SHIFT_MASK),
				JComponent.WHEN_FOCUSED);
	}

	// The Undo action
	public class UndoAction extends AbstractAction {
		public UndoAction(UndoManager manager) {
			this.manager = manager;
		}

		public void actionPerformed(ActionEvent evt) {
			try {
				manager.undo();
			} catch (CannotUndoException e) {
				Toolkit.getDefaultToolkit().beep();
			}
		}

		private UndoManager manager;
	}

	// The Redo action
	public class RedoAction extends AbstractAction {
		public RedoAction(UndoManager manager) {
			this.manager = manager;
		}

		public void actionPerformed(ActionEvent evt) {
			try {
				manager.redo();
			} catch (CannotRedoException e) {
				Toolkit.getDefaultToolkit().beep();
			}
		}

		private UndoManager manager;
	}

	/**
	 * 
	 * @author george
	 * 
	 */
	public class GEditorKit extends StyledEditorKit {

		private static final long serialVersionUID = 2969169649596107757L;
		private ViewFactory gViewFactory;

		public GEditorKit() {
			gViewFactory = new GViewFactory();
		}

		@Override
		public ViewFactory getViewFactory() {
			return gViewFactory;
		}

		@Override
		public String getContentType() {
			return "application/x-sql";
		}
	}

	/**
	 * 
	 * @author george
	 * 
	 */
	public class GViewFactory extends Object implements ViewFactory {

		/**
		 * @see javax.swing.text.ViewFactory#create(javax.swing.text.Element)
		 */
		public View create(Element element) {

			return new SQLView(element);
		}

	}

}